#include "stdafx.h"
#include "EXDateTimeCtrl.h"


IMPLEMENT_DYNAMIC(CEXDateTimeCtrl, CDateTimeCtrl)

CEXDateTimeCtrl::CEXDateTimeCtrl()
{
	m_bSetBitmap = FALSE;
	m_nTopHeight = 0;
	m_nBottomHeight = 0;
	m_nLeftWidth = 0;
	m_nRightWidth = 0;
	m_nBkgndID = 0;
	m_nNumOfBgPics = 0;
	m_crBkgnd = RGB(255, 0, 255);
	m_nSpinBkgndID = 0;
	m_nUpID = 0;
	m_nDownID = 0;
	m_pSpinButtonCtrl = NULL;
	m_bFocus = FALSE;
}

CEXDateTimeCtrl::~CEXDateTimeCtrl()
{
	if (m_pSpinButtonCtrl)
	{
		delete m_pSpinButtonCtrl;
	}
}


BEGIN_MESSAGE_MAP(CEXDateTimeCtrl, CDateTimeCtrl)
	ON_WM_SIZE()
	ON_WM_ERASEBKGND()
	ON_WM_MOUSEMOVE()
	ON_MESSAGE(WM_MOUSELEAVE, &CEXDateTimeCtrl::OnMouseLeaveNotify)
END_MESSAGE_MAP()



// CEXDateTimeCtrl message handlers


void CEXDateTimeCtrl::PreSubclassWindow()
{

	CDateTimeCtrl::PreSubclassWindow();
}

BOOL CEXDateTimeCtrl::SetBitmaps(UINT nBkgndID, UINT nSpinBkgndID, UINT nUpID,
                                 UINT nDownID, int nCount, COLORREF crBkgnd, 
                                 int nTopHeight /* = 0*/, int nBottomHeight /* = 0*/, 
                                 int nLeftWidth /* = 0*/, int nRightWidth /* = 0*/)
{
	ASSERT (GetStyle() & DTS_UPDOWN);

	m_nTopHeight = nTopHeight;
	m_nBottomHeight = nBottomHeight;
	m_nLeftWidth = nLeftWidth;
	m_nRightWidth = nRightWidth;

	m_nBkgndID = nBkgndID;
	m_nSpinBkgndID = nSpinBkgndID;
	m_nUpID = nUpID;
	m_nDownID = nDownID;
	m_nNumOfBgPics  = nCount;

	m_crBkgnd = crBkgnd;

  if (!m_pSpinButtonCtrl)
  {
    m_pSpinButtonCtrl = new CEXSpinButtonCtrl;
    VERIFY(m_pSpinButtonCtrl->SubclassWindow(::FindWindowEx(GetSafeHwnd(), 
      NULL, L"msctls_updown32", NULL)));
    VERIFY(m_pSpinButtonCtrl->SetBitmaps(m_nSpinBkgndID, m_nUpID, m_nDownID, 
      m_nNumOfBgPics, RGB(255,0,255),3,3,3,3));
  }

	CBitmap bmpTemp;
	if( !bmpTemp.LoadBitmap(m_nBkgndID) )
		return FALSE;

	m_bmpBkgnd.DeleteObject();

	if( !InitBgBitmap( bmpTemp, normal, m_nNumOfBgPics) ) 
		return FALSE;

	if( !InitBgBitmap( bmpTemp, focus, m_nNumOfBgPics) )
		return FALSE;

	if( !InitBgBitmap( bmpTemp, select, m_nNumOfBgPics) )
		return FALSE;

	if( !InitBgBitmap( bmpTemp, disable, m_nNumOfBgPics) )
		return FALSE;
  
	m_bSetBitmap = TRUE;

	return TRUE;
}

BOOL CEXDateTimeCtrl::InitBgBitmap(CBitmap & src, int index, int count)
{
	CDC * pDC = GetDC();

	CDC memDC; 
	memDC.CreateCompatibleDC(pDC);

	CDC srcDC;
	srcDC.CreateCompatibleDC(pDC);

	CBitmap* pOldBitmap1;
	pOldBitmap1 = srcDC.SelectObject(&src);

	BITMAP bmpinfo;
	src.GetBitmap(&bmpinfo);
	int bmpWidth = bmpinfo.bmWidth / count;
	int bmpHeight = bmpinfo.bmHeight;
	int orix = bmpWidth * (index < count ? index : 0);

	CRect rc, rcSpin;
	GetWindowRect(rc);
	rc.OffsetRect(-rc.left, -rc.top);

	CBitmap dist;
	dist.CreateCompatibleBitmap(pDC,rc.Width(),rc.Height());

	CBitmap* pOldBitmap2;
	pOldBitmap2 = memDC.SelectObject(&dist);
    
	memDC.FillSolidRect(rc, m_crBkgnd);

  if(!m_nTopHeight && !m_nRightWidth && !m_nLeftWidth && !m_nBottomHeight)
    memDC.StretchBlt(0, 0, rc.Width(), rc.Height() , &srcDC,
    orix, 0, bmpWidth, bmpHeight, SRCCOPY);
    
  else
  {
        // entireimage
    memDC.TransparentBlt(m_nLeftWidth,
		m_nTopHeight,
		rc.Width()  - ( m_nLeftWidth + m_nRightWidth ) ,
		rc.Height() -  ( m_nTopHeight + m_nBottomHeight) ,
		&srcDC,
		orix + m_nLeftWidth,
		m_nTopHeight,
		bmpWidth - ( m_nLeftWidth + m_nRightWidth ) ,
		bmpHeight - ( m_nTopHeight + m_nBottomHeight ) , m_crBkgnd);
    
	  // topbar
	  memDC.TransparentBlt(m_nLeftWidth,0, rc.Width() - 
                        (m_nLeftWidth + m_nRightWidth), m_nTopHeight,
                        &srcDC,orix + m_nLeftWidth, 0, bmpWidth - 
                        (m_nLeftWidth + m_nRightWidth), m_nTopHeight,m_crBkgnd);

	  // bottombar
	  memDC.TransparentBlt(m_nLeftWidth, rc.bottom-m_nBottomHeight, rc.Width() - 
                        ( m_nLeftWidth + m_nRightWidth), m_nBottomHeight,
                        &srcDC,orix + m_nLeftWidth, bmpHeight - m_nBottomHeight,
                        bmpWidth - ( m_nLeftWidth + m_nRightWidth), 
                        m_nBottomHeight, m_crBkgnd );

	  // sidebar
	  memDC.TransparentBlt(0,m_nTopHeight,m_nLeftWidth,rc.bottom - m_nTopHeight - 
                        m_nBottomHeight,
                        &srcDC, orix,m_nTopHeight, m_nLeftWidth, bmpHeight - 
                        ( m_nTopHeight + m_nBottomHeight ), m_crBkgnd);

	  memDC.TransparentBlt(rc.right - m_nRightWidth, m_nTopHeight, m_nRightWidth,
                        rc.bottom - m_nTopHeight - m_nBottomHeight,
                        &srcDC, orix +  bmpWidth - m_nRightWidth, m_nTopHeight, 
                        m_nRightWidth, bmpHeight - m_nTopHeight - 
                        m_nBottomHeight, m_crBkgnd);

	  // lefttop,leftbottom,righttop,rightbottom
	  if(!memDC.BitBlt(0,0,m_nLeftWidth, m_nTopHeight, &srcDC, orix, 0, SRCCOPY))
		  return FALSE;

	  if(!memDC.BitBlt(0, rc.bottom - m_nBottomHeight, m_nLeftWidth, 
          m_nBottomHeight, &srcDC, orix, bmpHeight - m_nBottomHeight, SRCCOPY))
		  return FALSE;

	  if(!memDC.BitBlt(rc.right - m_nRightWidth, 0, m_nRightWidth, m_nTopHeight, 
		                &srcDC, orix + bmpWidth - m_nRightWidth, 0, SRCCOPY))
		  return FALSE;

	  if(!memDC.BitBlt(rc.right - m_nRightWidth, rc.bottom - m_nBottomHeight,
                      m_nRightWidth, m_nBottomHeight,
                      &srcDC, orix + bmpWidth - m_nRightWidth, 
                      bmpHeight - m_nBottomHeight, SRCCOPY))
		  return FALSE;
  }
  
	if (!m_bmpBkgnd.GetSafeHandle())
		m_bmpBkgnd.CreateCompatibleBitmap(pDC, rc.Width()*count, rc.Height());

	CDC dcBkgn;
	dcBkgn.CreateCompatibleDC(pDC);

	CBitmap * pOldBitmap3 = dcBkgn.SelectObject(&m_bmpBkgnd);

	dcBkgn.BitBlt(rc.Width()*index, 0, rc.Width(), rc.Height(), 
                &memDC, 0, 0, SRCCOPY);

	srcDC.SelectObject(pOldBitmap1);
	memDC.SelectObject(pOldBitmap2);
	dcBkgn.SelectObject(pOldBitmap3);

	ReleaseDC(pDC);
	ReleaseDC(&srcDC);
	ReleaseDC(&memDC);

	return TRUE;
}

void CEXDateTimeCtrl::SetResSet(CEXBaseResSet* pResSet)
{
  m_pDTResSet = (CEXDateTimeCtrlResSet *)pResSet;

  SetFont(m_pDTResSet->m_font);

  if(m_pDTResSet->m_nType == DATETIME_CTRL)
    SetBitmaps(m_pDTResSet->m_nImgId, 
    m_pDTResSet->m_pSpinResSet->m_arrImgId.GetAt(0), 
    m_pDTResSet->m_pSpinResSet->m_arrImgId.GetAt(1), 
    m_pDTResSet->m_pSpinResSet->m_arrImgId.GetAt(2), 
    m_pDTResSet->m_nImg_DivideCnt, RGB(255, 255, 255));
}

void CEXDateTimeCtrl::OnSize(UINT nType, int cx, int cy)
{
	CDateTimeCtrl::OnSize(nType, cx, cy);

	if (IsWindow(GetSafeHwnd()) && m_bSetBitmap)
	{
		SetBitmaps(m_nBkgndID, m_nSpinBkgndID, m_nUpID, m_nDownID, m_nNumOfBgPics, 
            m_crBkgnd,m_nTopHeight,m_nBottomHeight,m_nLeftWidth,m_nRightWidth);
	}
}

void CEXDateTimeCtrl::DrawFrame(CDC * pDC)
{
	if (!m_bSetBitmap)
		return;

	CRect rcWnd, rcSpin;
	GetWindowRect(rcWnd);
	ScreenToClient(rcWnd);

	CDC dcBkgnd;
	dcBkgnd.CreateCompatibleDC(pDC);

	CBitmap bmpBkgnd;
	bmpBkgnd.CreateCompatibleBitmap(pDC, rcWnd.Width(), rcWnd.Height());

	CBitmap * pOldBmpBkgnd = NULL;
	pOldBmpBkgnd = dcBkgnd.SelectObject(&bmpBkgnd);

	CDC dcImage;
	dcImage.CreateCompatibleDC(pDC);

	STATUS st;

	if (!IsWindowEnabled())
	{
		st = disable;
	}
	else if (GetFocus() == this)
	{
		st = select;
	}
	else if (m_bFocus)
	{
		st = focus;
	}
	else
	{
		st = normal;
	}
  
	CBitmap* pOldBgBitmapImage = dcImage.SelectObject(&m_bmpBkgnd);
  
//	dcBkgnd.TransparentBlt(0, 0, rcWnd.Width(), rcWnd.Height(), &dcImage, 0, 0, rcWnd.Width(), rcWnd.Height(), m_crBkgnd);
	dcBkgnd.BitBlt(0, 0, rcWnd.Width(), rcWnd.Height(), &dcImage, 
               rcWnd.Width()*st, 0, SRCCOPY);

//	pDC->BitBlt(0, 0, rcWnd.Width(), rcWnd.Height(), &dcBkgnd, 0, 0, SRCCOPY);

  pDC->FillSolidRect(&rcWnd, m_crBkgnd);
  pDC->TransparentBlt(0, 0, rcWnd.Width(), rcWnd.Height(), &dcBkgnd, 0, 0, 
                     rcWnd.Width(), rcWnd.Height(), m_crBkgnd);



  CRect rct;
  GetClientRect(&rct);
  rct.right = rct.right - rct.Height();

  CString strText;
  GetWindowText(strText);
  CFont *f = GetFont();
  CFont *pf = (CFont*)pDC->SelectObject(f);

	rct.DeflateRect(2,2);
  CRect arText = rct;
 	pDC->SetBkMode(TRANSPARENT);
  pDC->DrawText(strText,&arText,DT_LEFT|DT_SINGLELINE|DT_VCENTER|DT_CALCRECT);
  pDC->DrawText(strText,&rct,DT_LEFT|DT_SINGLELINE|DT_VCENTER);

  m_pSpinButtonCtrl->RedrawWindow();
  pDC->SelectObject(pf);

  dcImage.SelectObject(pOldBgBitmapImage);
	dcBkgnd.SelectObject(pOldBmpBkgnd);
}

LRESULT CEXDateTimeCtrl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
  if (message == WM_PAINT && m_bSetBitmap)
  {
    CPaintDC dc(this);
    DrawFrame(&dc);
    
    return FALSE;
  }
  
  return CDateTimeCtrl::WindowProc(message, wParam, lParam);
}
BOOL CEXDateTimeCtrl::OnEraseBkgnd(CDC* pDC)
{
   if (m_bSetBitmap)
   {
     CWindowDC dc(this);
     DrawFrame(&dc);
//     Invalidate(FALSE);
     return FALSE;
   }
 	return CDateTimeCtrl::OnEraseBkgnd(pDC);
}

void CEXDateTimeCtrl::OnMouseMove(UINT nFlags, CPoint point)
{
	TRACKMOUSEEVENT tme = {0};
	tme.cbSize = sizeof tme;
	tme.dwFlags = TME_LEAVE;
	tme.hwndTrack = GetSafeHwnd();
	tme.dwHoverTime = 10;

	TrackMouseEvent(&tme);

	CRect rcWnd;
	GetWindowRect(rcWnd);
	ScreenToClient(rcWnd);

	BOOL bOldFocus = m_bFocus;

	if (rcWnd.PtInRect(point))
		m_bFocus = TRUE;
	else
		m_bFocus = FALSE;

	if ((bOldFocus != m_bFocus) && m_bSetBitmap)
	{
		CWindowDC dc(this);
		DrawFrame(&dc);
		InvalidateRgn(FALSE);
	}

	CDateTimeCtrl::OnMouseMove(nFlags, point);
}

LRESULT CEXDateTimeCtrl::OnMouseLeaveNotify(WPARAM w, LPARAM l)
{
	m_bFocus = FALSE;
	
	if (m_bSetBitmap)
	{
		CWindowDC dc(this);
		DrawFrame(&dc);
		InvalidateRgn(FALSE);
	}

	return 0;
}
